# -*- coding:utf-8 -*-

# author: firstoneyuan
#email: devops_yj@163.com

"""
# 1. 单个节点
# 2. 多个节点
"""

# 1. 基本使用
"""
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC 
from selenium.webdriver.support.wait import WebDriverWait

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
    input = browser.find_element_by_id('kw')
    input.send_keys('Python')
    input.send_keys(Keys.ENTER)
    wait = WebDriverWait(browser,10)
    wait.until(EC.presence_of_element_located((By.ID,'content_left')))
    print(browser.current_url)
    print(browser.get_cookies())
    print(browser.page_source)
finally:
    browser.close()
# 弹出chrome浏览器,跳转到百度,在搜索框中输入Python,再跳转到搜索结果页. 控制台分别输出当前的URL,当前的Cookies和网页源代码.
"""


# 2. 单个节点
# 提取淘宝搜索框，先观察源代码. Elements选项卡.
"""
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input_first = browser.find_element_by_id('q')  #根据ID获取。

# 根据CSS选择器获取
input_second = browser.find_element_by_css_selector('#q')
input_third = browser.find_element_by_xpath('//*[@id="q"]')  #根据XPath获取.
print(input_first,input_second,input_third)
browser.close()
'''
输出结果:
<selenium.webdriver.remote.webelement.WebElement (session="da5b1c1dfc6e6914495bf04dab80c92b", element="0.4082269017944622-1")> <selenium.webdriver.remote.webelement.WebElement (session="da5b1c1dfc6e6914495bf04dab80c92b", element="0.4082269017944622-1")> <selenium.webdriver.remote.webelement.WebElement (session="da5b1c1dfc6e6914495bf04dab80c92b", element="0.4082269017944622-1")>
这3个节点都是WebElement类型的.
'''

# find_element(By.ID,id)方法
from selenium import webdriver
from selenium.webdriver.common.by import By 

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input_first = browser.find_element(By.ID,'q')
print(input_first)
browser.close()
# 输出结果: <selenium.webdriver.remote.webelement.WebElement (session="88095c203f3452895d457b4bcea13c70", element="0.6253174545873144-1")>
"""


# 3. 多个节点
# 查找淘宝左侧导航条的所有条目
"""
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
lis = browser.find_elements_by_css_selector('.service-bd li')
print(lis)
browser.close()
# 得到的内容变成了列表类型,列表中的每个节点都是WebElement类型.
"""

# 4. 节点交互
# 驱动浏览器来执行一些操作.
#   - 输入文字用`send_keys()`方法.
#   - 清空文字时用`clear()`方法.
#   - 点击按钮用`click()`方法.
"""
from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input = browser.find_element_by_id('q')
input.send_keys('iPhone')
time.sleep(1)
input.clear()
input.send_keys('iPad')
button = browser.find_element_by_class_name('btn-search')
button.click()
time.sleep(5)
browser.close()
'''
先用浏览器打开淘宝,然后用find_element_by_id方法获取输入框,然后用send_keys方法输入iPhone文字,等待一秒后用clear()方法清空输入框,再次调用send_keys()方法输入iPad文字，之后再用find_element_by_class_name()方法获取搜索按钮,最后调用click方法完成搜索动作.
'''
"""

# 5. 动作链
# 实现一个节点的拖拽操作,将某个节点从一处拖拽到另外一处.
"""
from selenium import webdriver
from selenium.webdriver import ActionChains

browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
source = browser.find_element_by_css_selector('#draggable')
target = browser.find_element_by_css_selector('#droppable')
actions = ActionChains(browser)
actions.drag_and_drop(source,target)
actions.perform()
'''
首先，打开网页中的一个拖拽实例,然后依次选中要拖拽的节点和拖拽的目标节点,接着声明ActionChains对象并将其赋值为actions变量,然后通过调用actions变量的drag_and_drop()方法,再调用perform()方法执行动作,此时就完成了拖拽操作.
'''
"""


# 6. 执行JavaScript
# 下拉进度条,它可以直接模拟运行JavaScript, 此时使用execute_script()方法实现.
"""
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
browser.execute_script('alert("To Bottom")')
# 利用execute_script方法将进度条下拉到最底部,然后弹出alert提示框.
"""


# 7. 获取节点信息
# 7.1 获取属性
# 用get_attribute()方法来获取节点的属性.其前提是先选中这个节点.
"""
from selenium import webdriver
from selenium.webdriver import ActionChains

browser = webdriver.Chrome()
url = 'https://www.zhihu.com/explore'
browser.get(url)
logo = browser.find_element_by_id('zh-top-link-logo')
print(logo)
print(logo.get_attribute('class'))
'''
打开知乎页面，获取知乎的logo节点,打印class.
<selenium.webdriver.remote.webelement.WebElement (session="88a82290450960a3ecd6d29ea86b77c7", element="0.5099538832575008-1")>
zu-top-link-logo
'''
# 通过get_attribute方法,然后传入想要获取的属性名,就可以得到它的值.
"""


# 7.2 获取文本值
# 每个WebElement节点都有text属性,直接调用这个属性可以得到节点内部的文本信息.
"""
from selenium import webdriver

browser = webdriver.Chrome()
url = 'https://www.zhihu.com/explore'
browser.get(url)
input = browser.find_element_by_class_name('zu-top-add-question')
print(input.text)
# 打开知乎页面，获取"提问"按钮这个节点,再将其文本值打印出来.输出为:提问
"""

# 7.3 获取id,位置,标签名和大小
# WebElement节点还有一些其他属性: id属性获取节点id,location属性获取该节点在页面中的相对位置. tag_name属性可以获取标签名称,size属性可以获取节点的大小(宽高)
"""
from selenium import webdriver

browser = webdriver.Chrome()
url = 'https://www.zhihu.com/explore'
browser.get(url)
input = browser.find_element_by_class_name('zu-top-add-question')
print(input.id)
print(input.location)
print(input.tag_name)
print(input.size)
# 先获得"提问"按钮这个节点,再调用其id,location,tag_name,size属性来获取对应的属性值.
'''
0.798784569935771-1
{'x': 762, 'y': 7}
button
{'height': 32, 'width': 66}
'''
"""


# 7.4 切换Frame
# 网页中有一种节点叫做iframe,也就是子Frame,相当于页面的子页面,它的结构和外部网页结构完全一致. Selenium打开页面后,它默认是在父级Frame里面操作,此时如果页面中还有子Frame,它是不能获取到子Frame里面的节点的. 需要使用switch_to.frame方法来却换Frame。
"""
import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
try:
    logo = browser.find_element_by_class_name('logo')
except NoSuchElementException:
    print('NO logo')
browser.switch_to.parent_frame()
logo = browser.find_element_by_class_name('logo')
print(logo)
print(logo.text)
'''
输出:
NO logo
<selenium.webdriver.remote.webelement.WebElement (session="66b3f2343306ec7
a25216c45ae5680b3", element="0.17214469324638415-2")>
RUNOOB.COM
以前面演示动作链操作的网页为实例,先通过switch_to.frame方法切换到子Frame里面,然后尝试获取父级Frame里的logo节点,如果找不到,就返回NoSuchElementException异常,异常被捕捉后,就输出NO logo。 接下来，重新切换会父级Frame,然后再次重新获取节点,发现此时就可以成功获取了.
'''
# 当页面中包含子Frame时,如果想获取子Frame中的节点,需要先调用switch_to.frame方法切换到对应的Frame,然后再进行操作.
"""




# 8. 延时等待
# 8.1 隐式等待
# 当查找节点而节点没有立即出现时,隐式等待将等待一段时间再查找DOM,默认的时间是0.
'''
from selenium import webdriver

browser = webdriver.Chrome()
browser.implicitly_wait(10)
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)
'''

# 8.2 显式等待
# 它指定要查找的节点,然后指定一个最长等待时间。在规定时间内加载出来这个节点,就返回查找的节点;到了规定时间没有加载出该节点,则抛出超时异常.
"""
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC 

browser = webdriver.Chrome()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser,10)
input = wait.until(EC.presence_of_element_located((By.ID,'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search')))
print(input,button)
'''
先引入WebDriverWait这个对象,指定最长等待时间,然后调用它的until方法,传入要等待条件expected_conditions, 例如: 这里传入了presence_of_element_located这个条件,代表节点出现的意思,其参数是节点的定位元组,也就是ID为q的节点搜索框.
在10秒内如果ID为q的节点(即搜索框)成功加载出来,就返回该节点,如果超时并没有加载出来,就抛出异常.

对于按钮,可以更改一下等待条件,比如改为element_to_be_clickable，也就是可点击,所以查找按钮时查找CSS选择器为.btn-search的按钮,如果10秒内它是可点击的,也就是成功加载出来了.就返回这个按钮节点,超过10秒还不可点击,没有加载出来,就抛出异常.
输出结果:
<selenium.webdriver.remote.webelement.WebElement (session="5eb3ad7cf34ff
d6a021d35870180e42b", element="0.05272480271518032-1")> <selenium.webdri
ver.remote.webelement.WebElement (session="5eb3ad7cf34ffd6a021d35870180e
42b", element="0.05272480271518032-2")>

他们都是WebElement类型.
'''
"""

# 9. 前进和后退
# 使用back()方法后退,使用forward方法前进.
"""
import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.get('https://www.python.org/')
browser.back()
time.sleep(2)
browser.forward()
time.sleep(6)
browser.close()
# 连续访问3个页面,然后调用back方法回到第二个页面,再调用forward方法回到第三个页面。
"""

# 10 Cookies
"""
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name':'name','domain':'www.zhihu.com','value':'germey'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())
'''
访问知乎,加载完成后,浏览器生成Cookies,调用get_cookies()方法获取所有的Cookies,然后，添加一个Cookie,这里传入一个字典,有name,domain和value等内容. 再次获取所有的Cookies, 最后调用delete_all_cookies()方法删除所有的Cookies，再重新获取，发现结果为空.
'''
"""


# 11. 选项卡管理
"""
import time
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()')
print(browser.window_handles)
browser.switch_to_window(browser.window_handles[1])
browser.get('https://www.taobao.com')
time.sleep(1)
browser.switch_to_window(browser.window_handles[0])
browser.get('https://python.org')
'''
访问百度,调用execute_script方法,传入window.open()这个JavaScript语句新开启一个选项卡. 切换到该选项卡,调用window_handles属性获取当前开启的所有选项卡,返回的是选项卡的代号列表. 要想切换选项卡,只需要调用switch_to_window()方法即可.其中参数是选项卡的代号. 这里将第二哥选项卡代号传入,即跳转到第二个选项卡,接下来在第二个选项卡打开一个新页面,然后切换回第一个选项卡重新调用switch_to_window()方法，再执行其他操作即可.
'''
"""

# 12. 异常处理
# 使用try except语句来捕获各种异常.
# 演示一下节点未找到的异常
"""
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://www.baidu.com')
browser.find_element_by_id('hello')
# 打开百度页面,尝试选择一个并不存在的节点就会遇到异常.
'''
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"id","selector":"hello"}
'''
"""

# 捕获异常
from selenium import webdriver
from selenium.common.exceptions import TimeoutException,NoSuchElementException

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('Time Out')
try:
    browser.find_element_by_id('hello')
except NoSuchElementException:
    print('No Element')
finally:
    browser.close()

  
